import React, {PropsWithChildren, useCallback, useEffect, useMemo, useState} from 'react'
import {View} from "@tarojs/components";
import styles from "./QueryGoodsList.module.sass"
import {Button, SearchBar, Space, VirtualList} from "@nutui/nutui-react-taro";
import {FilterH} from "@nutui/icons-react-taro";
import {queryGoods, AddOrderItemKey, SubGoodsResponse} from "../apis/GoodsApi";
import GoodsListItem, {GoodsListItemData} from "./GoodsListItem";
import {Pageable} from "../utils/Page";
import ArrayUtils from "@zxy-cn/array-utils"
import ScanBarcodeButton from "./ScanBarcodeButton";
import QueryGoodsListFilterDrawer from "./QueryGoodsListFilterDrawer";
import {goodsPageStackStore} from "../store/GoodsPageStackStore";
import {observer} from "mobx-react";

export interface QueryGoodsListProps extends PropsWithChildren {
    editMarketOrderId?: number
    editProcurementId?: number,
    editProcurementReceiptId?: number
    excludeGoodsIds?: number[]
    onSelectedGoodsIdListChange?: (selectedGoodsIdList: AddOrderItemKey[]) => void
    existedGoodsList?: QueryGoodsListExistedItem[]
}

export interface QueryGoodsListExistedItem {
    id: number
    name: string
    barcode: string
    subGoods?: SubGoodsResponse
}

/**
 * Reuse this component on some page to select goods, Support multi select
 */
const QueryGoodsList: React.FC<QueryGoodsListProps> = ({
                                                           editMarketOrderId,
                                                           editProcurementId,
                                                           editProcurementReceiptId,
                                                           excludeGoodsIds,
                                                           onSelectedGoodsIdListChange,
                                                           existedGoodsList
                                                       }) => {
    const selectedKeys = useMemo(() => {
        return existedGoodsList?.map(it => ({goodsId: it.id, subGoodsId: it.subGoods?.id}))
    }, [existedGoodsList])

    const multiSelect = useMemo(() => true, [])
    const [selectedGoodsKeyList, setSelectedGoodsKeyList] = useState<AddOrderItemKey[]>([])
    useEffect(() => {
        onSelectedGoodsIdListChange && onSelectedGoodsIdListChange(selectedGoodsKeyList)
    }, [selectedGoodsKeyList]);

    const selectMode = useMemo(() => {
        return !!editMarketOrderId || !!excludeGoodsIds || !!editProcurementId || !!editProcurementReceiptId
    }, [editMarketOrderId, excludeGoodsIds, editProcurementId, editProcurementReceiptId]);

    const [searchNameText, setSearchNameText] = useState<string>("")
    const [searchInputValue, setSearchInputValue] = useState("")
    const [loading, setLoading] = useState(false)
    const [selectedBrandIds, setSelectedBrandIds] = useState<number[]>([])
    const [selectedCategoryIds, setSelectedCategoryIds] = useState<number[]>([])
    const [selectedFactoryIds, setSelectedFactoryIds] = useState<number[]>([])
    useEffect(() => {
        goodsPageStackStore.resetListAndPageable()
    }, [selectedBrandIds, selectedCategoryIds, selectedFactoryIds]);

    const queryWithoutPageable = useCallback((pageable: Pageable) => {
        // if (goodsPageStackStore.list.length <= pageable.page * pageable.size && !loading && !goodsPageStackStore.last) {
        setLoading(true)
        queryGoods({
            nameOrBarcode: searchNameText || undefined,
            editMarketOrderId,
            editProcurementId,
            editProcurementReceiptId,
            excludeIds: excludeGoodsIds,
            brandIds: selectedBrandIds,
            factoryIds: selectedFactoryIds,
            categoryIds: selectedCategoryIds,
        }, pageable).then(res => {
            goodsPageStackStore.appendItems(res.data)
        }).finally(() => {
            setLoading(false)
        })
        // }
    }, [searchNameText, selectedCategoryIds, selectedFactoryIds, selectedBrandIds,]);
    const query = useCallback(() => {
        queryWithoutPageable(goodsPageStackStore.pageable)
    }, [searchNameText, ...goodsPageStackStore.pageable.toDependencyList(), selectedCategoryIds, selectedFactoryIds, selectedBrandIds,])


    useEffect(() => {
        query()
    }, [query]);

    const onSearch = useCallback((value: string) => {
        setSearchNameText(value)
        if (value !== searchNameText) {
            goodsPageStackStore.resetListAndPageable()
        }
    }, [searchNameText]);

    function setInputValueAndSearch(value: string) {
        setSearchInputValue(value)
        onSearch(value)
    }


    const items = useMemo(() => {
        let value = searchNameText.trim().toLowerCase();
        let array:GoodsListItemData[] = goodsPageStackStore.list.filter(it => {
            return !selectedKeys?.some(key => key.goodsId === it.id && !key.subGoodsId)
        }).flatMap(item => {
            return !!item.subGoodsList.length ? item.subGoodsList.filter(sub => {
                return !selectedKeys?.some(key => key.goodsId === item.id && key.subGoodsId === sub.id)
            }).filter(sub => {

                return !value || sub.name.toLowerCase().includes(value) || sub.number.toLowerCase().includes(value);
            }).map(sub => {
                return {
                    ...item,
                    subGoods: sub,
                }
            }) : item
        });
        if (goodsPageStackStore.last) {
            array = array.concat(existedGoodsList?.filter(it => it.name.toLowerCase().includes(value) || it.barcode.toLowerCase().includes(value) || it.subGoods?.name.toLowerCase().includes(value) || it.subGoods?.number.toLowerCase().includes(value))
                .map(it=>({
                    ...it,
                    subGoods:it.subGoods,
                    existed:true,
                }))??[])
        }
        return array
    }, [goodsPageStackStore.list, selectedKeys, searchNameText, goodsPageStackStore.last]);

    const [showFilterDrawer, setShowFilterDrawer] = useState(false)


    return <>
        <QueryGoodsListFilterDrawer onConfirm={data => {
            setSelectedBrandIds(data.brandIds)
            setSelectedCategoryIds(data.categoryIds)
            setSelectedFactoryIds(data.factoryIds)
        }} visible={showFilterDrawer} onClose={() => setShowFilterDrawer(false)}/>
        <View className={styles.container}>
            <SearchBar placeholder={"品名或条码"} shape="round" right={
                <Space>
                    <ScanBarcodeButton size={"small"} onScanSuccess={async (barcode, _) => {
                        setInputValueAndSearch(barcode)
                    }}/>
                    <Button type={"primary"} size={"small"} loading={loading} onClick={() => {
                        onSearch(searchInputValue)
                    }}>搜索</Button>
                </Space>
            } inputMode={"search"} left={<FilterH
                color={selectedCategoryIds.length || selectedFactoryIds.length || selectedBrandIds.length ? "#fa2c19" : undefined}
                onClick={() => {
                    setShowFilterDrawer(true)
                }}/>} onChange={value => {
                setSearchInputValue(value)
            }} onSearch={onSearch} onClear={() => {
                setInputValueAndSearch("")
            }}/>
            <VirtualList itemEqual itemHeight={66} className={styles.scrollView} onScroll={() => {
                if (!goodsPageStackStore.last && !loading) {
                    goodsPageStackStore.next()
                }
            }} list={items} itemRender={(item: GoodsListItemData & {existed?:boolean}) => <GoodsListItem
                disabled={item.existed}
                key={item.id + (item.subGoods?.number ?? "")}
                checked={item.existed?true:selectedGoodsKeyList.some(it => it.goodsId === item.id && it.subGoodsId == item.subGoods?.id)}
                data={item} style={{margin: 0}}
                onCheckChange={selectMode && multiSelect ? (item.existed?()=>{}:checked => {
                    const array = Array.from(selectedGoodsKeyList)
                    if (checked) {
                        array.push({goodsId: item.id, subGoodsId: item.subGoods?.id})
                    } else {
                        ArrayUtils.removeBy(array, it => it.goodsId === item.id && it.subGoodsId == item.subGoods?.id)
                    }
                    setSelectedGoodsKeyList(array)
                }) : undefined}/>}/>
        </View>
    </>
}

export default observer(QueryGoodsList)


